﻿#include "StdAfx.h"
#include "PrivateCloud.h"
#include <ws2ipdef.h>
#include "md5.h"

//////////////////////////////////////////////////////////////////////////
// class CPrivateCloudHelper

CPrivateCloudHelper::CPrivateCloudHelper()
{
	m_hThread = INVALID_HANDLE_VALUE;
	m_hSocket = INVALID_SOCKET;
	m_lpCallbackRoutine = NULL;
	m_lpCallbackContext = NULL;

	WSADATA wsaData = {0};
	WSAStartup(MAKEWORD(2, 2), &wsaData);
}

CPrivateCloudHelper::~CPrivateCloudHelper()
{
	EndSearch();
	WSACleanup();
}

DWORD WINAPI CPrivateCloudHelper::SearchThread(LPVOID lpContext)
{
	TRACE(_T("_PRIVATECLOUD_SEARCH_WORKER_\r\n"));

	CPrivateCloudHelper *pCloud = (CPrivateCloudHelper *) lpContext;

	pCloud->m_hSocket = socket(AF_INET, SOCK_DGRAM, 0);
	if (pCloud->m_hSocket == INVALID_SOCKET)
	{
		TRACE(_T("SearchThread: socket error: %d\r\n"), WSAGetLastError());
		return -1;
	}

	struct sockaddr_in self_addr = {0};
	self_addr.sin_family = AF_INET;
	self_addr.sin_addr.s_addr = htonl(INADDR_ANY);
	self_addr.sin_port = htons(UDP_RECV_PORT);

	//@code
	// 绑定端口，我们通过此端口接收回应消息
	//@endcode
	if (bind(pCloud->m_hSocket, (struct sockaddr *) &self_addr, sizeof(self_addr)) == SOCKET_ERROR)
	{
		TRACE(_T("SearchThread: bind error: %d\r\n"), WSAGetLastError());
		closesocket(pCloud->m_hSocket);
		pCloud->m_hSocket = INVALID_SOCKET;
		return -1;
	}

	//@code
	// 设置广播选项
	//@endcode
	struct ip_mreq mreq;
	mreq.imr_multiaddr.s_addr = htonl(BROADCAST_ADDRESS);
	mreq.imr_interface.s_addr = htonl(INADDR_ANY);

	setsockopt(pCloud->m_hSocket, IPPROTO_IP, IP_MULTICAST_IF, (const char *) &mreq.imr_interface.s_addr, sizeof(struct in_addr)); 
	setsockopt(pCloud->m_hSocket, IPPROTO_IP, IP_ADD_MEMBERSHIP, (const char *) &mreq, sizeof(mreq));

	// 广播地址
	struct sockaddr_in broadcast_addr = {0};
	broadcast_addr.sin_family = AF_INET;
	broadcast_addr.sin_addr.s_addr = htonl(BROADCAST_ADDRESS);
	broadcast_addr.sin_port = htons(UDP_BROADCAST_PORT);

	if (_tcslen(pCloud->m_szCloudId) == 0)
	{
		// 搜索局域网的所有云
		CLOUDMSG_SEARCHALL msg = {0};
		msg.hdr.Cmd = CloudCmd_SearchAll;
		msg.hdr.Length = sizeof(CLOUDMSG_SEARCHALL);
		CPrivateCloudHelper::Package((LPCLOUDMSG_HDR) &msg);
		sendto(pCloud->m_hSocket, (const char *) &msg, sizeof(msg), 0, (struct sockaddr *) &broadcast_addr, sizeof(broadcast_addr));
		Sleep(0);
		sendto(pCloud->m_hSocket, (const char *) &msg, sizeof(msg), 0, (struct sockaddr *) &broadcast_addr, sizeof(broadcast_addr));
		Sleep(0);
		sendto(pCloud->m_hSocket, (const char *) &msg, sizeof(msg), 0, (struct sockaddr *) &broadcast_addr, sizeof(broadcast_addr));
	}
	else
	{
		// 搜索局域网的指定云
		CLOUDMSG_SEARCH msg = {0};
		msg.hdr.Cmd = CloudCmd_Search;
		msg.hdr.Length = sizeof(CLOUDMSG_SEARCH);
		_tcscpy_s(msg.CloudId, _countof(msg.CloudId), pCloud->m_szCloudId);
		CPrivateCloudHelper::Package((LPCLOUDMSG_HDR) &msg);
		sendto(pCloud->m_hSocket, (const char *) &msg, sizeof(msg), 0, (struct sockaddr *) &broadcast_addr, sizeof(broadcast_addr));
		Sleep(0);
		sendto(pCloud->m_hSocket, (const char *) &msg, sizeof(msg), 0, (struct sockaddr *) &broadcast_addr, sizeof(broadcast_addr));
		Sleep(0);
		sendto(pCloud->m_hSocket, (const char *) &msg, sizeof(msg), 0, (struct sockaddr *) &broadcast_addr, sizeof(broadcast_addr));
	}

	struct sockaddr_in peer_addr = {0};
	BYTE buffer[MAX_PACKET_SIZE];
	int len;
	int recved;

	// 获取本机IP信息
	char hostname[256];
	gethostname(hostname, sizeof(hostname));
	struct hostent *host = gethostbyname(hostname);

	while (TRUE)
	{
		len = sizeof(peer_addr);

		// 接收应答消息
		recved = recvfrom(pCloud->m_hSocket, (char *) buffer, MAX_PACKET_SIZE, 0, (struct sockaddr *) &peer_addr, &len);
		if (recved <= 0)
		{
			break;
		}

		// 判断消息是否来自本机
		if (host != NULL)
		{
			char **p = host->h_addr_list;
			while (*p != NULL)
			{
				struct sockaddr_in addr = {0};
				memcpy(&addr.sin_addr.S_un.S_addr, *p, host->h_length);
				if (addr.sin_addr.S_un.S_addr == peer_addr.sin_addr.S_un.S_addr)
				{
					TRACE(_T("From self\r\n"));
					break;
				}
				p++;
			}

			// 来自本机，忽略
			if (*p != NULL)
				continue;
		}

		if (recved >= sizeof(CLOUDMSG_HDR))
		{
			LPCLOUDMSG_HDR hdr = (LPCLOUDMSG_HDR) buffer;
			if (CPrivateCloudHelper::Verify(hdr))
			{
				if (hdr->Cmd == CloudCmd_SearchAllAck)
				{
					TRACE(_T("Find: %s-%s\r\n"), ((LPCLOUDMSG_SEARCHALL_ACK) buffer)->CloudId, ((LPCLOUDMSG_SEARCHALL_ACK) buffer)->CloudName);

					CPrivateCloudHelper::CALLBACK_ITEM item;
					item.peer_ip = peer_addr.sin_addr.S_un.S_addr;
					item.hdr = (LPCLOUDMSG_HDR) buffer;
					pCloud->m_lpCallbackRoutine(CloudCallbackReason_Recv, &item, pCloud->m_lpCallbackContext);
				}
				else if (hdr->Cmd == CloudCmd_SearchAck)
				{
					TRACE(_T("Find: %s\r\n"), pCloud->m_szCloudId);

					CPrivateCloudHelper::CALLBACK_ITEM item;
					item.peer_ip = peer_addr.sin_addr.S_un.S_addr;
					item.hdr = (LPCLOUDMSG_HDR) buffer;
					pCloud->m_lpCallbackRoutine(CloudCallbackReason_Recv, &item, pCloud->m_lpCallbackContext);
				}
			}
		}
	}

	return 0;
}

VOID CPrivateCloudHelper::RegisterCallback(LPCLOUD_CALLBACK lpCallbackRoutine, DWORD_PTR lpContext)
{
	m_lpCallbackRoutine = lpCallbackRoutine;
	m_lpCallbackContext = lpContext;
}

DWORD CPrivateCloudHelper::BeginSearch(LPCTSTR lpszCloudId)
{
	// 等待上一次搜索结束
	EndSearch();

	// 重新开始新的搜索
	if (lpszCloudId)
		_tcscpy_s(m_szCloudId, _countof(m_szCloudId), lpszCloudId);
	else
		_tcscpy_s(m_szCloudId, _countof(m_szCloudId), _T("\0"));
	m_hThread = CreateThread(NULL, 0, SearchThread, this, 0, NULL);
	return GetLastError();
}

VOID CPrivateCloudHelper::EndSearch()
{
	if (m_hSocket != INVALID_SOCKET)
	{
		closesocket(m_hSocket);
		m_hSocket = NULL;
	}

	if (m_hThread != INVALID_HANDLE_VALUE)
	{
		WaitForSingleObject(m_hThread, INFINITE);
		CloseHandle(m_hThread);
		m_hThread = NULL;
	}
}

BOOL CPrivateCloudHelper::GenerateToken(IN LPTSTR lpszTokenMask, IN LPTSTR lpszTokenMask2, IN LPTSTR lpszPassword, OUT LPBYTE lpToken)
{
	CString sToken;
	sToken += lpszTokenMask;
	sToken += lpszTokenMask2;
	sToken += lpszPassword;
	
	MD5_CTX md5_ctx;
	MD5Init(&md5_ctx);
	MD5Update(&md5_ctx, (unsigned char *) sToken.GetBuffer(), sToken.GetLength() * sizeof(TCHAR));
	MD5Final(lpToken, &md5_ctx);
	return TRUE;
}

BOOL CPrivateCloudHelper::GenerateRandomTokenMask(OUT LPTSTR lpszTokenMask)
{
	srand(GetTickCount());

	for (int i = 0; i < TOKEN_MASK_LENGTH - 1; i++)
	{
		lpszTokenMask[i] = (rand() % 26) + _T('A');
	}

	lpszTokenMask[TOKEN_MASK_LENGTH - 1] = _T('\0');
	return TRUE;
}

int CPrivateCloudHelper::CRC(char *p, int length)
{
	register unsigned char l, h, t;
	l = h = 0xff;
	for ( int i = 0; i < length; i++ )
	{
		h^= p[i];
		h^= h>>4;
		t = h;
		h = l;
		l = t;
		t = (l << 4) | (l >> 4);
		h^= ((t << 2) | (t >> 6)) & 0x1f;
		h^= t & 0xf0;
		l^= ((t << 1) | (t >> 7)) & 0xe0;
	}
	return ((int)h<<8) | l;
}

VOID CPrivateCloudHelper::Package(LPCLOUDMSG_HDR hdr)
{
	hdr->Signature = CLOUD_SIGNATURE;
	hdr->Version = CLOUD_VERSION_1_0;
	hdr->CRC = 0; // 在计算CRC之前必须把CRC置为0
	hdr->CRC = CRC((char *) hdr, hdr->Length);
}

BOOL CPrivateCloudHelper::VerifyHeader(LPCLOUDMSG_HDR hdr)
{
	if (hdr->Signature != CLOUD_SIGNATURE || hdr->Version != CLOUD_VERSION_1_0)
		return FALSE;

	if (hdr->Length < sizeof(CLOUDMSG_HDR))
		return FALSE;

	if (hdr->Length > MAX_PACKET_SIZE)
		return FALSE;

	return TRUE;
}

BOOL CPrivateCloudHelper::Verify(LPCLOUDMSG_HDR hdr)
{
	if (!VerifyHeader(hdr))
		return FALSE;

	int nCRC = hdr->CRC; // 保存CRC
	hdr->CRC = 0; // 在计算CRC之前必须把CRC置为0
	if (nCRC != CRC((char *) hdr, hdr->Length))
	{
		hdr->CRC = nCRC; // 恢复之前保存的值
		return FALSE;
	}

	hdr->CRC = nCRC; // 恢复之前保存的值
	return TRUE;
}

//////////////////////////////////////////////////////////////////////////
// class CPrivateCloud

CPrivateCloud::CPrivateCloud()
{
	m_bConnected = FALSE;
	m_hUdpListenThread = INVALID_HANDLE_VALUE;
	m_hTcpListenThread = INVALID_HANDLE_VALUE;
	m_hUdpListenSocket = INVALID_SOCKET;
	m_hTcpListenSocket = INVALID_SOCKET;
	m_hHeartbeatThread = INVALID_HANDLE_VALUE;
	m_hTerminateEvent = INVALID_HANDLE_VALUE;
	m_lpCallbackRoutine = NULL;
	m_lpCallbackContext = NULL;

	WSADATA wsaData = {0};
	WSAStartup(MAKEWORD(2, 2), &wsaData);
}

CPrivateCloud::~CPrivateCloud()
{
	DisconnectAll();
	WSACleanup();
}

// 监听UDP广播的线程
DWORD WINAPI CPrivateCloud::UdpListenThread(LPVOID lpContext)
{
	TRACE(_T("UdpListenThread\r\n"));

	CPrivateCloud *pCloud = (CPrivateCloud *) lpContext;

	pCloud->m_hUdpListenSocket = socket(AF_INET, SOCK_DGRAM, 0);
	if (pCloud->m_hUdpListenSocket == INVALID_SOCKET)
	{
		TRACE(_T("UdpListenThread: socket error: %d\r\n"), WSAGetLastError());
		pCloud->Callback(CloudCallbackReason_CloudError, NULL, WSAGetLastError());
		return -1;
	}

	struct sockaddr_in self_addr = {0};
	self_addr.sin_family = AF_INET;
	self_addr.sin_addr.s_addr = htonl(INADDR_ANY); // htonl(BROADCAST_ADDRESS); 
	self_addr.sin_port = htons(UDP_BROADCAST_PORT);

	// 绑定端口，我们通过此端口接收广播消息
	if (bind(pCloud->m_hUdpListenSocket, (struct sockaddr *) &self_addr, sizeof(self_addr)) == SOCKET_ERROR)
	{
		TRACE(_T("UdpListenThread: bind error: %d\r\n"), WSAGetLastError());
		pCloud->Callback(CloudCallbackReason_CloudError, NULL, WSAGetLastError());
		return -1;
	}

	// 设置广播选项
	struct ip_mreq mreq;
	mreq.imr_multiaddr.s_addr = htonl(BROADCAST_ADDRESS);
	mreq.imr_interface.s_addr = htonl(INADDR_ANY);

	setsockopt(pCloud->m_hUdpListenSocket, IPPROTO_IP, IP_MULTICAST_IF, (const char *) &mreq.imr_interface.s_addr, sizeof(struct in_addr)); 
	setsockopt(pCloud->m_hUdpListenSocket, IPPROTO_IP, IP_ADD_MEMBERSHIP, (const char *) &mreq, sizeof(mreq));

	struct sockaddr_in peer_addr = {0};
	BYTE buffer[MAX_PACKET_SIZE];
	int len;
	int recved;

	while (TRUE)
	{
		len = sizeof(peer_addr);

		// 接收广播消息
		recved = recvfrom(pCloud->m_hUdpListenSocket, (char *) buffer, MAX_PACKET_SIZE, 0, (struct sockaddr *) &peer_addr, &len);
		if (recved <= 0)
			break;

		TRACE(_T("UdpListenThread: recvfrom return %d\r\n"), recved);

		if (recved >= sizeof(CLOUDMSG_HDR))
		{
			LPCLOUDMSG_HDR hdr = (LPCLOUDMSG_HDR) buffer;
			if (CPrivateCloudHelper::Verify(hdr))
			{
				TRACE(_T("UdpListenThread: message cmd = 0x%08x\r\n"), hdr->Cmd);

				if (hdr->Cmd == CloudCmd_SearchAll)
				{
					// 告诉对方本私有云的信息
					CLOUDMSG_SEARCHALL_ACK msg = {0};
					msg.hdr.Cmd = CloudCmd_SearchAllAck;
					msg.hdr.Length = sizeof(CLOUDMSG_SEARCHALL_ACK);
					_tcscpy_s(msg.CloudId, _countof(msg.CloudId), pCloud->m_szCloudId);
					_tcscpy_s(msg.CloudName, _countof(msg.CloudName), pCloud->m_szCloudName);
					CPrivateCloudHelper::Package((LPCLOUDMSG_HDR) &msg);
					sendto(pCloud->m_hUdpListenSocket, (const char *) &msg, sizeof(msg), 0, (struct sockaddr *) &peer_addr, sizeof(peer_addr));
					Sleep(0);
					sendto(pCloud->m_hUdpListenSocket, (const char *) &msg, sizeof(msg), 0, (struct sockaddr *) &peer_addr, sizeof(peer_addr));
					Sleep(0);
					sendto(pCloud->m_hUdpListenSocket, (const char *) &msg, sizeof(msg), 0, (struct sockaddr *) &peer_addr, sizeof(peer_addr));
				}
				else if (hdr->Cmd == CloudCmd_Search)
				{
					// 判断是不是我们的云
					LPCLOUDMSG_SEARCH lpSearchMsg = (LPCLOUDMSG_SEARCH) buffer;
					if (_tcscmp(lpSearchMsg->CloudId, pCloud->m_szCloudId) == 0)
					{
						CLOUDMSG_SEARCH_ACK msg = {0};
						msg.hdr.Cmd = CloudCmd_SearchAck;
						msg.hdr.Length = sizeof(CLOUDMSG_SEARCH_ACK);
						CPrivateCloudHelper::Package((LPCLOUDMSG_HDR) &msg);
						sendto(pCloud->m_hUdpListenSocket, (const char *) &msg, sizeof(msg), 0, (struct sockaddr *) &peer_addr, sizeof(peer_addr));
						Sleep(0);
						sendto(pCloud->m_hUdpListenSocket, (const char *) &msg, sizeof(msg), 0, (struct sockaddr *) &peer_addr, sizeof(peer_addr));
						Sleep(0);
						sendto(pCloud->m_hUdpListenSocket, (const char *) &msg, sizeof(msg), 0, (struct sockaddr *) &peer_addr, sizeof(peer_addr));
					}
				}
			}
		}
	}

	return 0;
}

// 监听TCP连接的线程
DWORD WINAPI CPrivateCloud::TcpListenThread(LPVOID lpContext)
{
	TRACE(_T("TcpListenThread\r\n"));

	CPrivateCloud *pCloud = (CPrivateCloud *) lpContext;

	pCloud->m_hTcpListenSocket = socket(AF_INET, SOCK_STREAM, 0);
	if (pCloud->m_hTcpListenSocket == INVALID_SOCKET)
	{
		TRACE(_T("TcpListenThread; socket error: %d\r\n"), WSAGetLastError());
		pCloud->Callback(CloudCallbackReason_CloudError, NULL, WSAGetLastError());
		return -1;
	}

	struct sockaddr_in self_addr = {0};
	self_addr.sin_family = AF_INET;
	self_addr.sin_addr.s_addr = htonl(INADDR_ANY);
	self_addr.sin_port = htons(TCP_LISTEN_PORT);

	int flag = 1;
	setsockopt(pCloud->m_hTcpListenSocket, SOL_SOCKET, SO_REUSEADDR, (const char *) &flag, sizeof(flag));

	// 绑定端口，我们通过此端口接收消息
	if (bind(pCloud->m_hTcpListenSocket, (struct sockaddr *) &self_addr, sizeof(self_addr)) == SOCKET_ERROR)
	{
		TRACE(_T("TcpListenThread; bind error: %d\r\n"), WSAGetLastError());
		pCloud->Callback(CloudCallbackReason_CloudError, NULL, WSAGetLastError());
		return -1;
	}

	// 开始监听
	if (listen(pCloud->m_hTcpListenSocket, 5) == SOCKET_ERROR)
	{
		TRACE(_T("listen error: %d\r\n"), WSAGetLastError());
		pCloud->Callback(CloudCallbackReason_CloudError, NULL, WSAGetLastError());
		return -1;
	}

	while (TRUE)
	{
		struct sockaddr_in peer_addr = {0};
		int len = sizeof(peer_addr);

		// 收到一个请求
		SOCKET s = accept(pCloud->m_hTcpListenSocket, (struct sockaddr *) &peer_addr, &len);
		if (s == INVALID_SOCKET)
			break;

		long ip = peer_addr.sin_addr.S_un.S_addr;

		// 首先判断当前是否已经有此ip连接，有则关闭上次的连接
		{
			CSingleLock	lock(&pCloud->m_cs, TRUE);

			if (pCloud->m_cDeviceList.count(ip) != 0)
			{
				if (pCloud->m_cDeviceList[ip].hServerThread != INVALID_HANDLE_VALUE)
				{
					pCloud->DisconnectFromDevice(ip);
				}
			}
		}

		// 创建一个线程来处理此连接请求
		CPrivateCloud::LPCONNECT_CONTEXT lpContext = new CPrivateCloud::CONNECT_CONTEXT;
		lpContext->pCloud = pCloud;
		lpContext->bRunAsServer = TRUE;
		lpContext->ip = ip;

		HANDLE hThread = CreateThread(NULL, 0, MessageThread, lpContext, CREATE_SUSPENDED, NULL);
		if (hThread == INVALID_HANDLE_VALUE)
		{
			delete lpContext;
		}
		else
		{
			CSingleLock	lock(&pCloud->m_cs, TRUE);

			if (pCloud->m_cDeviceList.count(ip) == 0)
			{
				pCloud->m_cDeviceList[ip].ip = ip;
				pCloud->m_cDeviceList[ip].hClientThread = INVALID_HANDLE_VALUE;
				pCloud->m_cDeviceList[ip].hClientSocket = INVALID_SOCKET;
				pCloud->m_cDeviceList[ip].bDeviceInformationOK = FALSE;
				pCloud->m_cDeviceList[ip].hEvent = INVALID_HANDLE_VALUE;
				pCloud->m_cDeviceList[ip].bTerminated = FALSE;
				pCloud->m_cDeviceList[ip].bConnected = FALSE;
			}

			pCloud->m_cDeviceList[ip].hServerThread = hThread;
			pCloud->m_cDeviceList[ip].hServerSocket = s;

			ResumeThread(hThread);
		}
	}

	return 0;
}

// 处理发送或者接收消息的线程
DWORD WINAPI CPrivateCloud::MessageThread(LPVOID lpContext)
{
	TRACE(_T("MessageThread\r\n"));

	CPrivateCloud::LPCONNECT_CONTEXT lpConnectContext = (CPrivateCloud::LPCONNECT_CONTEXT) lpContext;
	CPrivateCloud *pCloud = lpConnectContext->pCloud;
	BOOL bRunAsServer = lpConnectContext->bRunAsServer;
	long ip = lpConnectContext->ip;
	BYTE buffer[MAX_PACKET_SIZE];
	SOCKET s;
	int sent;
	int recved;

	delete lpConnectContext;

	if (!bRunAsServer)
	{
		TRACE(_T("MessageThread: RunAsClient\r\n"));

		s = pCloud->m_cDeviceList[ip].hClientSocket;

		TCHAR szMyTokenMask[TOKEN_MASK_LENGTH] = _T("");
		CPrivateCloudHelper::GenerateRandomTokenMask(szMyTokenMask);

		TCHAR szPeerTokenMask[TOKEN_MASK_LENGTH] = _T("");

		// 交换TokenMask信息，用于认证
		CLOUDMSG_EXCHANGE_TOKEN_MASK tokenMask = {0};
		tokenMask.hdr.Cmd = CloudCmd_ExchangeTokenMask;
		tokenMask.hdr.Length = sizeof(CLOUDMSG_EXCHANGE_TOKEN_MASK);
		_tcscpy_s(tokenMask.TokenMask, _countof(tokenMask.TokenMask), szMyTokenMask);
		CPrivateCloudHelper::Package((LPCLOUDMSG_HDR) &tokenMask);
		sent = send(s, (char *) &tokenMask, sizeof(tokenMask), 0);
		if (sent != sizeof(tokenMask))
		{
			TRACE(_T("send error: %d\r\n"), WSAGetLastError());
			pCloud->Callback(CloudCallbackReason_Error, ip, WSAGetLastError());
			return -1;
		}

		pCloud->Callback(CloudCallbackReason_Send, ip, (DWORD_PTR) &tokenMask);

		// 接收TokenMask结果
		recved = recv(s, (char *) buffer, sizeof(CLOUDMSG_EXCHANGE_TOKEN_MASK_ACK), 0);
		if (recved == -1 || recved < sizeof(CLOUDMSG_EXCHANGE_TOKEN_MASK_ACK))
		{
			TRACE(_T("send error: %d\r\n"), WSAGetLastError());
			pCloud->Callback(CloudCallbackReason_Error, ip, WSAGetLastError());
			return WSAGetLastError();
		}

		LPCLOUDMSG_EXCHANGE_TOKEN_MASK_ACK tokenMaskAck = (LPCLOUDMSG_EXCHANGE_TOKEN_MASK_ACK) buffer;
		if (!CPrivateCloudHelper::Verify((LPCLOUDMSG_HDR) tokenMaskAck))
		{
			TRACE(_T("invalid message\r\n"));
			pCloud->Callback(CloudCallbackReason_Error, ip, NULL);
			return -1;
		}
		else if (tokenMaskAck->hdr.Cmd != CloudCmd_ExchangeTokenMaskAck)
		{
			TRACE(_T("invalid command\r\n"));
			pCloud->Callback(CloudCallbackReason_Error, ip, NULL);
			return -1;
		}

		// 记录对方返回的TokenMask
		_tcscpy_s(szPeerTokenMask, _countof(szPeerTokenMask), tokenMaskAck->TokenMask);

		pCloud->Callback(CloudCallbackReason_Recv, ip, (DWORD_PTR) tokenMaskAck);

		// 进行身份验证
		CLOUDMSG_LOGIN login = {0};
		login.hdr.Cmd = CloudCmd_Login;
		login.hdr.Length = sizeof(CLOUDMSG_LOGIN);
		// 生成Token，记住我们的TokenMask作为第一个参数，对方的TokenMask作为第二个参数，验证的时候顺序相反
		CPrivateCloudHelper::GenerateToken(szMyTokenMask, szPeerTokenMask, pCloud->m_szPassword, login.Token);
		CPrivateCloudHelper::Package((LPCLOUDMSG_HDR) &login);
		sent = send(s, (char *) &login, sizeof(login), 0);
		if (sent != sizeof(login))
		{
			TRACE(_T("send error: %d\r\n"), WSAGetLastError());
			pCloud->Callback(CloudCallbackReason_Error, ip, WSAGetLastError());
			return -1;
		}

		pCloud->Callback(CloudCallbackReason_Send, ip, (DWORD_PTR) &login);

		// 接收验证结果
		recved = recv(s, (char *) buffer, sizeof(CLOUDMSG_LOGIN_ACK), 0);
		if (recved == -1 || recved < sizeof(CLOUDMSG_LOGIN_ACK))
		{
			TRACE(_T("send error: %d\r\n"), WSAGetLastError());
			pCloud->Callback(CloudCallbackReason_Error, ip, WSAGetLastError());
			return WSAGetLastError();
		}

		LPCLOUDMSG_LOGIN_ACK loginAck = (LPCLOUDMSG_LOGIN_ACK) buffer;
		if (!CPrivateCloudHelper::Verify((LPCLOUDMSG_HDR) loginAck))
		{
			TRACE(_T("invalid message\r\n"));
			pCloud->Callback(CloudCallbackReason_Error, ip, NULL);
			return -1;
		}
		else if (loginAck->hdr.Cmd != CloudCmd_LoginAck)
		{
			TRACE(_T("invalid command\r\n"));
			pCloud->Callback(CloudCallbackReason_Error, ip, NULL);
			return -1;
		}
		else if ( loginAck->Result == FALSE)
		{
			pCloud->Callback(CloudCallbackReason_LoginError, ip, NULL);
			return -1;
		}

		pCloud->Callback(CloudCallbackReason_Recv, ip, (DWORD_PTR) loginAck);

		// 验证结束，进入循环发送命令过程
		do
		{
			if (pCloud->m_cDeviceList[ip].bTerminated)
				break;

			CSingleLock lock(&pCloud->m_cs, TRUE);

			while (pCloud->m_cDeviceList[ip].cTaskList.size() > 0)
			{
				LPCLOUDMSG_HDR hdr = pCloud->m_cDeviceList[ip].cTaskList.front();

				// 每次发送的数据包不超过1400，超过的进行分片发送
				DWORD dwLeft = hdr->Length;
				char *lpBuffer = (char *) hdr;
				while (dwLeft > 0)
				{
					sent = send(s, lpBuffer, dwLeft, 0);
					if (sent <= 0)
					{
						TRACE(_T("send error: %d\r\n"), WSAGetLastError());
						pCloud->Callback(CloudCallbackReason_Error, ip, WSAGetLastError());
						return -1;
					}

					dwLeft -= sent;
					lpBuffer += sent;
				}

				pCloud->Callback(CloudCallbackReason_Send, ip, (DWORD_PTR) hdr);

				pCloud->m_cDeviceList[ip].cTaskList.pop_front();
				delete hdr;
			}
		} while (WAIT_OBJECT_0 == WaitForSingleObject(pCloud->m_cDeviceList[ip].hEvent, INFINITE));
	}
	else
	{
		TRACE(_T("MessageThread: RunAsServer\r\n"));

		s = pCloud->m_cDeviceList[ip].hServerSocket;

		TCHAR szMyTokenMask[TOKEN_MASK_LENGTH] = _T("");
		CPrivateCloudHelper::GenerateRandomTokenMask(szMyTokenMask);

		TCHAR szPeerTokenMask[TOKEN_MASK_LENGTH] = _T("");

		// 等待对方发送交换TokenMask信息
		recved = recv(s, (char *) buffer, sizeof(CLOUDMSG_EXCHANGE_TOKEN_MASK), 0);
		if (recved == -1 || recved < sizeof(CLOUDMSG_EXCHANGE_TOKEN_MASK))
		{
			TRACE(_T("recv error: %d\r\n"), WSAGetLastError());
			pCloud->Callback(CloudCallbackReason_Error, ip, WSAGetLastError());
			return -1;
		}

		LPCLOUDMSG_EXCHANGE_TOKEN_MASK tokenMask = (LPCLOUDMSG_EXCHANGE_TOKEN_MASK) buffer;
		if (!CPrivateCloudHelper::Verify((LPCLOUDMSG_HDR) tokenMask))
		{
			TRACE(_T("invalid message\r\n"));
			pCloud->Callback(CloudCallbackReason_Error, ip, NULL);
			return -1;
		}
		else if (tokenMask->hdr.Cmd != CloudCmd_ExchangeTokenMask)
		{
			TRACE(_T("invalid command\r\n"));
			pCloud->Callback(CloudCallbackReason_Error, ip, NULL);
			return -1;
		}

		// 记住对方的TokenMask
		_tcscpy_s(szPeerTokenMask, _countof(szPeerTokenMask), tokenMask->TokenMask);

		pCloud->Callback(CloudCallbackReason_Recv, ip, (DWORD_PTR) tokenMask);

		// 发送回应
		CLOUDMSG_EXCHANGE_TOKEN_MASK_ACK tokenMaskAck = {0};
		tokenMaskAck.hdr.Cmd = CloudCmd_ExchangeTokenMaskAck;
		tokenMaskAck.hdr.Length = sizeof(CLOUDMSG_EXCHANGE_TOKEN_MASK_ACK);
		_tcscpy_s(tokenMaskAck.TokenMask, _countof(tokenMaskAck.TokenMask), szMyTokenMask);
		CPrivateCloudHelper::Package((LPCLOUDMSG_HDR) &tokenMaskAck);
		sent = send(s, (char *) &tokenMaskAck, sizeof(tokenMaskAck), 0);
		if (sent != sizeof(tokenMaskAck))
		{
			TRACE(_T("send error: %d\r\n"), WSAGetLastError());
			pCloud->Callback(CloudCallbackReason_Error, ip, WSAGetLastError());
			return -1;
		}

		pCloud->Callback(CloudCallbackReason_Send, ip, (DWORD_PTR) &tokenMaskAck);

		// 等待对方发送验证信息
		recved = recv(s, (char *) buffer, sizeof(CLOUDMSG_LOGIN), 0);
		if (recved == -1 || recved < sizeof(CLOUDMSG_LOGIN))
		{
			TRACE(_T("recv error: %d\r\n"), WSAGetLastError());
			pCloud->Callback(CloudCallbackReason_Error, ip, WSAGetLastError());
			return -1;
		}

		LPCLOUDMSG_LOGIN login = (LPCLOUDMSG_LOGIN) buffer;
		if (!CPrivateCloudHelper::Verify((LPCLOUDMSG_HDR) login))
		{
			TRACE(_T("invalid message\r\n"));
			pCloud->Callback(CloudCallbackReason_Error, ip, NULL);
			return -1;
		}
		else if (login->hdr.Cmd != CloudCmd_Login)
		{
			TRACE(_T("invalid command\r\n"));
			pCloud->Callback(CloudCallbackReason_Error, ip, NULL);
			return -1;
		}

		BYTE szToken[TOKEN_LENGTH];
		// 生成Token，记住我们的TokenMask作为第二个参数，对方的TokenMask作为第一个参数，和我们主动去验证的顺序相反
		CPrivateCloudHelper::GenerateToken(szPeerTokenMask, szMyTokenMask, pCloud->m_szPassword, szToken);
		if (memcmp(szToken, login->Token, TOKEN_LENGTH) != 0)
		{
			TRACE(_T("Token error: %s-%s\r\n"), szToken, login->Token);
			pCloud->Callback(CloudCallbackReason_LoginError, ip, NULL);
			return -1;
		}

		pCloud->Callback(CloudCallbackReason_Recv, ip, (DWORD_PTR) login);

		// 通知对方验证通过
		CLOUDMSG_LOGIN_ACK loginAck = {0};
		loginAck.hdr.Cmd = CloudCmd_LoginAck;
		loginAck.hdr.Length = sizeof(CLOUDMSG_LOGIN_ACK);
		loginAck.Result = TRUE;
		CPrivateCloudHelper::Package((LPCLOUDMSG_HDR) &loginAck);
		sent = send(s, (char *) &loginAck, sizeof(loginAck), 0);
		if (sent != sizeof(loginAck))
		{
			TRACE(_T("send error: %d\r\n"), WSAGetLastError());
			pCloud->Callback(CloudCallbackReason_Error, ip, WSAGetLastError());
			return -1;
		}

		pCloud->Callback(CloudCallbackReason_Send, ip, (DWORD_PTR) &loginAck);

		// 主动连接对方（和每个云设备都要建立两个连接，一个用于发送命令，一个用于接收命令）
		{
			CSingleLock lock(&pCloud->m_cs, TRUE);

			if (!pCloud->m_cDeviceList[ip].bConnected)
			{
				pCloud->ConnectToDevice(ip);
			}
		}

		// 验证通过，进入消息处理过程
		while ((recved = recv(s, (char *) buffer, sizeof(CLOUDMSG_HDR), 0)) > 0)
		{
			if (recved == sizeof(CLOUDMSG_HDR))
			{
				LPCLOUDMSG_HDR hdr = (LPCLOUDMSG_HDR) buffer;
				if (!CPrivateCloudHelper::VerifyHeader((LPCLOUDMSG_HDR) buffer))
				{
					TRACE(_T("invalid message header\r\n"));
					pCloud->Callback(CloudCallbackReason_Error, ip, NULL);
					return -1;
				}

				// 读取剩下的数据包
				int nLeft = hdr->Length - sizeof(CLOUDMSG_HDR);
				int nPos = sizeof(CLOUDMSG_HDR);
				while (nLeft > 0)
				{
					if (nLeft > 1024)
						recved = recv(s, (char *) &buffer[nPos], 1024, 0);
					else
						recved = recv(s, (char *) &buffer[nPos], nLeft, 0);
					if (recved <= 0)
					{
						TRACE(_T("recv error: %d\r\n"), WSAGetLastError());
						pCloud->Callback(CloudCallbackReason_Error, ip, WSAGetLastError());
						return -1;
					}

					nLeft -= recved;
					nPos += recved;
				}

				if (!CPrivateCloudHelper::Verify((LPCLOUDMSG_HDR) buffer))
				{
					TRACE(_T("invalid message\r\n"));
					pCloud->Callback(CloudCallbackReason_Error, ip, NULL);
					return -1;
				}

				switch (hdr->Cmd)
				{
				case CloudCmd_ExchangeInformation:
					{
						TRACE(_T("CloudCmd_ExchangeInformation\r\n"));

						LPCLOUDMSG_EXCHANGE_INFORMATION lpDevice = (LPCLOUDMSG_EXCHANGE_INFORMATION) buffer;

						// 记住对方的设备信息
						{
							CSingleLock lock(&pCloud->m_cs, TRUE);
							_tcscpy_s(pCloud->m_cDeviceList[ip].szDeviceId, _countof(pCloud->m_cDeviceList[ip].szDeviceId), lpDevice->DeviceId);
							_tcscpy_s(pCloud->m_cDeviceList[ip].szDeviceName, _countof(pCloud->m_cDeviceList[ip].szDeviceName), lpDevice->DeviceName);
							_tcscpy_s(pCloud->m_cDeviceList[ip].szDeviceType, _countof(pCloud->m_cDeviceList[ip].szDeviceType), lpDevice->DeviceType);
							pCloud->m_cDeviceList[ip].bDeviceInformationOK = FALSE;
						}

						pCloud->Callback(CloudCallbackReason_Recv, ip, (DWORD_PTR) hdr);
					}
					break;

				case CloudCmd_ExchangeInformationAck:
					{
						TRACE(_T("CloudCmd_ExchangeInformationAck\r\n"));
						pCloud->Callback(CloudCallbackReason_Recv, ip, (DWORD_PTR) hdr);
					}
					break;

				case CloudCmd_SearchOther:
					{
						TRACE(_T("CloudCmd_SearchOther\r\n"));
						pCloud->Callback(CloudCallbackReason_Recv, ip, (DWORD_PTR) hdr);
					}
					break;

				case CloudCmd_SearchOtherAck:
					{
						TRACE(_T("CloudCmd_SearchOtherAck\r\n"));
						pCloud->Callback(CloudCallbackReason_Recv, ip, (DWORD_PTR) hdr);
					}
					break;

				case CloudCmd_ReportFile:
					{
						TRACE(_T("CloudCmd_ReportFile\r\n"));
						pCloud->Callback(CloudCallbackReason_Recv, ip, (DWORD_PTR) hdr);
					}
					break;

				case CloudCmd_ReportFileAck:
					{
						TRACE(_T("CloudCmd_ReportFileAck\r\n"));
						pCloud->Callback(CloudCallbackReason_Recv, ip, (DWORD_PTR) hdr);
					}
					break;

				case CloudCmd_NewFile:
					{
						TRACE(_T("CloudCmd_NewFile\r\n"));
						pCloud->Callback(CloudCallbackReason_Recv, ip, (DWORD_PTR) hdr);
					}
					break;

				case CloudCmd_NewFileAck:
					{
						TRACE(_T("CloudCmd_NewFileAck\r\n"));
						pCloud->Callback(CloudCallbackReason_Recv, ip, (DWORD_PTR) hdr);
					}
					break;

				case CloudCmd_DeleteFile:
					{
						TRACE(_T("CloudCmd_DeleteFile\r\n"));
						pCloud->Callback(CloudCallbackReason_Recv, ip, (DWORD_PTR) hdr);
					}
					break;

				case CloudCmd_DeleteFileAck:
					{
						TRACE(_T("CloudCmd_DeleteFileAck\r\n"));
						pCloud->Callback(CloudCallbackReason_Recv, ip, (DWORD_PTR) hdr);
					}
					break;

				case CloudCmd_DownloadFile:
					{
						TRACE(_T("CloudCmd_DownloadFile\r\n"));
						pCloud->Callback(CloudCallbackReason_Recv, ip, (DWORD_PTR) hdr);
					}
					break;

				case CloudCmd_DownloadFileAck:
					{
						TRACE(_T("CloudCmd_DownloadFileAck\r\n"));
						pCloud->Callback(CloudCallbackReason_Recv, ip, (DWORD_PTR) hdr);
					}
					break;

				case CloudCmd_UploadFile:
					{
						TRACE(_T("CloudCmd_UploadFile\r\n"));
						pCloud->Callback(CloudCallbackReason_Recv, ip, (DWORD_PTR) hdr);
					}
					break;

				case CloudCmd_UploadFileAck:
					{
						TRACE(_T("CloudCmd_UploadFileAck\r\n"));
						pCloud->Callback(CloudCallbackReason_Recv, ip, (DWORD_PTR) hdr);
					}
					break;

				case CloudCmd_RefreshFile:
					{
						TRACE(_T("CloudCmd_RefreshFile\r\n"));
						pCloud->Callback(CloudCallbackReason_Recv, ip, (DWORD_PTR) hdr);
					}
					break;

				case CloudCmd_RefreshFileAck:
					{
						TRACE(_T("CloudCmd_RefreshFileAck\r\n"));
						pCloud->Callback(CloudCallbackReason_Recv, ip, (DWORD_PTR) hdr);
					}
					break;

				case CloudCmd_DownloadAddressBook:
					{
						TRACE(_T("CloudCmd_DownloadAddressBook\r\n"));
						pCloud->Callback(CloudCallbackReason_Recv, ip, (DWORD_PTR) hdr);
					}
					break;

				case CloudCmd_DownloadAddressBookAck:
					{
						TRACE(_T("CloudCmd_DownloadAddressBookAck\r\n"));
						pCloud->Callback(CloudCallbackReason_Recv, ip, (DWORD_PTR) hdr);
					}
					break;

				default:
					{
						TRACE(_T("Unknown command\r\n"));
						pCloud->Callback(CloudCallbackReason_Recv, ip, (DWORD_PTR) hdr);
					}
					break;
				}
			}
			else
			{
				TRACE(_T("recv an invalid message\r\n"));
			}
		}
	}

	return 0;
}

// 发送心跳消息的线程
DWORD WINAPI CPrivateCloud::HeartbeatThread(LPVOID lpContext)
{
	TRACE(_T("HeartbeatThread\r\n"));

	CPrivateCloud *pCloud = (CPrivateCloud *) lpContext;

	CLOUDMSG_HDR heartbeat;
	heartbeat.Cmd = CloudCmd_Heartbeat;
	heartbeat.Length = sizeof(CLOUDMSG_HDR);
	CPrivateCloudHelper::Package((LPCLOUDMSG_HDR) &heartbeat);

	while (WAIT_TIMEOUT == WaitForSingleObject(pCloud->m_hTerminateEvent, HEARTBEAT_INTERVAL))
	{
		CSingleLock	lock(&pCloud->m_cs, TRUE);

		std::map<long, CPrivateCloud::PRIVATECLOUD_ITEM>::iterator iter;
		for (iter = pCloud->m_cDeviceList.begin(); iter != pCloud->m_cDeviceList.end(); ++iter)
		{
			// 判断是否已经连接并验证通过，只有验证通过后才发送心跳信息
			if (iter->second.bConnected)
			{
				pCloud->PostTask(iter->second.ip, &heartbeat);
			}
		}
	}

	return 0;
}

VOID CPrivateCloud::SetDeviceInformation(LPCTSTR lpszDeviceId, LPCTSTR lpszDeviceName, LPCTSTR lpszDeviceType)
{
	_tcscpy_s(m_szDeviceId, _countof(m_szDeviceId), lpszDeviceId);
	_tcscpy_s(m_szDeviceName, _countof(m_szDeviceName), lpszDeviceName);
	_tcscpy_s(m_szDeviceType, _countof(m_szDeviceType), lpszDeviceType);
}

VOID CPrivateCloud::RegisterCallback(LPCLOUD_CALLBACK lpCallbackRoutine, DWORD_PTR lpContext)
{
	m_lpCallbackRoutine = lpCallbackRoutine;
	m_lpCallbackContext = lpContext;
}

DWORD CPrivateCloud::ConnectToCloud(LPTSTR lpszCloudId, LPTSTR lpszCloudName, LPTSTR lpszPassword)
{
	DWORD dwError = ERROR_SUCCESS;

	// 保存云的相关信息
	_tcscpy_s(m_szCloudId, _countof(m_szCloudId), lpszCloudId);
	_tcscpy_s(m_szCloudName, _countof(m_szCloudName), lpszCloudName);
	_tcscpy_s(m_szPassword, _countof(m_szPassword), lpszPassword);

	// 用来通知心跳线程结束
	m_hTerminateEvent = CreateEvent(NULL, TRUE, FALSE, NULL);

	// 创建监听线程和心跳线程
	m_hUdpListenThread = CreateThread(NULL, 0, UdpListenThread, this, CREATE_SUSPENDED, NULL);
	if (m_hUdpListenThread != INVALID_HANDLE_VALUE)
	{
		m_hTcpListenThread = CreateThread(NULL, 0, TcpListenThread, this, CREATE_SUSPENDED, NULL);
		if (m_hTcpListenThread != INVALID_HANDLE_VALUE)
		{
			m_hHeartbeatThread = CreateThread(NULL, 0, HeartbeatThread, this, 0, NULL);
			if (m_hHeartbeatThread != INVALID_HANDLE_VALUE)
			{
				ResumeThread(m_hUdpListenThread);
				ResumeThread(m_hTcpListenThread);
				m_bConnected = TRUE;
			}
			else
			{
				dwError = GetLastError();
				CloseHandle(m_hTcpListenThread);
				m_hTcpListenThread = NULL;
				CloseHandle(m_hUdpListenThread);
				m_hUdpListenThread = NULL;
			}
		}
		else
		{
			dwError = GetLastError();
			CloseHandle(m_hUdpListenThread);
			m_hUdpListenThread = NULL;
		}
	}
	else
	{
		dwError = GetLastError();
	}

	return dwError;
}

BOOL CPrivateCloud::IsCloudConnected()
{
	return m_bConnected;
}

DWORD CPrivateCloud::ConnectToDevice(long ip)
{
	SOCKET s = socket(AF_INET, SOCK_STREAM, 0);
	if (s == INVALID_SOCKET)
	{
		DWORD dwError = WSAGetLastError();
		TRACE(_T("socket error: %d\r\n"), dwError);
		return dwError;
	}

	struct sockaddr_in peer_addr = {0};
	peer_addr.sin_family = AF_INET;
	peer_addr.sin_addr.S_un.S_addr = ip;
	peer_addr.sin_port = htons(TCP_LISTEN_PORT);

	int flag = 1;
	setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (const char *) &flag, sizeof(flag));

	if (connect(s, (struct sockaddr *) &peer_addr, sizeof(peer_addr)) == SOCKET_ERROR)
	{
		DWORD dwError = WSAGetLastError();
		TRACE(_T("connect error: %d\r\n"), dwError);
		closesocket(s);
		return dwError;
	}

	LPCONNECT_CONTEXT lpContext = new CONNECT_CONTEXT;
	lpContext->pCloud = this;
	lpContext->bRunAsServer = FALSE;
	lpContext->ip = ip;

	// 在线程中处理具体的网络消息
	HANDLE hThread = CreateThread(NULL, 0, MessageThread, lpContext, CREATE_SUSPENDED, NULL);
	if (hThread == INVALID_HANDLE_VALUE)
	{
		DWORD dwError = GetLastError();
		TRACE(_T("CreateThread error: %d\r\n"), dwError);
		delete lpContext;
		closesocket(s);
		return dwError;
	}

	CSingleLock	lock(&m_cs, TRUE);

	if (m_cDeviceList.count(ip) == 0)
	{
		m_cDeviceList[ip].ip = ip;
		m_cDeviceList[ip].hServerThread = INVALID_HANDLE_VALUE;
		m_cDeviceList[ip].hServerSocket = INVALID_SOCKET;
		m_cDeviceList[ip].bDeviceInformationOK = FALSE;
	}

	m_cDeviceList[ip].hClientThread = hThread;
	m_cDeviceList[ip].hClientSocket = s;
	m_cDeviceList[ip].bTerminated = FALSE;
	m_cDeviceList[ip].hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
	m_cDeviceList[ip].bConnected = TRUE;

	ResumeThread(hThread);

	return ERROR_SUCCESS;
}

VOID CPrivateCloud::DisconnectFromDevice(long ip)
{
	CSingleLock	lock(&m_cs, TRUE);

	if (m_cDeviceList.count(ip) != 0)
	{
		if (m_cDeviceList[ip].hClientSocket != INVALID_SOCKET)
		{
			closesocket(m_cDeviceList[ip].hClientSocket);
			m_cDeviceList[ip].hClientSocket = INVALID_SOCKET;
		}

		if (m_cDeviceList[ip].hServerSocket != INVALID_SOCKET)
		{
			closesocket(m_cDeviceList[ip].hServerSocket);
			m_cDeviceList[ip].hServerSocket = INVALID_SOCKET;
		}

		m_cDeviceList[ip].bTerminated = TRUE;
		if (m_cDeviceList[ip].hEvent != INVALID_HANDLE_VALUE)
		{
			SetEvent(m_cDeviceList[ip].hEvent);
		}

		if (m_cDeviceList[ip].hClientThread != INVALID_HANDLE_VALUE)
		{
			WaitForSingleObject(m_cDeviceList[ip].hClientThread, INFINITE);
			CloseHandle(m_cDeviceList[ip].hClientThread);
			m_cDeviceList[ip].hClientThread = NULL;
		}

		if (m_cDeviceList[ip].hServerThread != INVALID_HANDLE_VALUE)
		{
			WaitForSingleObject(m_cDeviceList[ip].hServerThread, INFINITE);
			CloseHandle(m_cDeviceList[ip].hServerThread);
			m_cDeviceList[ip].hServerThread = NULL;
		}

		// 清除所有未发送的任务
		while (m_cDeviceList[ip].cTaskList.size() > 0)
		{
			LPCLOUDMSG_HDR hdr = m_cDeviceList[ip].cTaskList.front();
			m_cDeviceList[ip].cTaskList.pop_front();
			delete hdr;
		}

		m_cDeviceList[ip].bConnected = FALSE;
	}
}

VOID CPrivateCloud::DisconnectAll()
{
	if (m_hTerminateEvent != INVALID_HANDLE_VALUE)
	{
		SetEvent(m_hTerminateEvent);
		CloseHandle(m_hTerminateEvent);
		m_hTerminateEvent = INVALID_HANDLE_VALUE;
	}

	if (m_hUdpListenSocket != INVALID_SOCKET)
	{
		closesocket(m_hUdpListenSocket);
		m_hUdpListenSocket = NULL;
	}

	if (m_hTcpListenSocket != INVALID_SOCKET)
	{
		closesocket(m_hTcpListenSocket);
		m_hTcpListenSocket = NULL;
	}

	if (m_hUdpListenThread != INVALID_HANDLE_VALUE)
	{
		WaitForSingleObject(m_hUdpListenThread, INFINITE);
		CloseHandle(m_hUdpListenThread);
		m_hUdpListenThread = INVALID_HANDLE_VALUE;
	}

	if (m_hTcpListenThread != INVALID_HANDLE_VALUE)
	{
		WaitForSingleObject(m_hTcpListenThread, INFINITE);
		CloseHandle(m_hTcpListenThread);
		m_hTcpListenThread = INVALID_HANDLE_VALUE;
	}

	{
		CSingleLock	lock(&m_cs, TRUE);

		std::map<long, PRIVATECLOUD_ITEM>::iterator iter;
		for (iter = m_cDeviceList.begin(); iter != m_cDeviceList.end(); ++iter)
		{
			DisconnectFromDevice(iter->second.ip);
		}
	}

	m_bConnected = FALSE;
}

BOOL CPrivateCloud::PostTask(long ip, LPCLOUDMSG_HDR lpMsg)
{
	CSingleLock	lock(&m_cs, TRUE);

	LPCLOUDMSG_HDR lpBuffer = (LPCLOUDMSG_HDR) new BYTE[lpMsg->Length];
	memcpy(lpBuffer, lpMsg, lpMsg->Length);

	std::map<long, PRIVATECLOUD_ITEM>::iterator iter;
	for (iter = m_cDeviceList.begin(); iter != m_cDeviceList.end(); ++iter)
	{
		if (iter->second.ip == ip)
		{
			iter->second.cTaskList.push_back(lpBuffer);
			SetEvent(iter->second.hEvent);
			return TRUE;
		}
	}

	TRACE(_T("PostTask error\r\n"));
	delete lpBuffer;
	return FALSE;
}

BOOL CPrivateCloud::Callback(DWORD dwReason, long ip, DWORD_PTR lpBuffer)
{
	CPrivateCloud::CALLBACK_ITEM item;
	item.peer_ip = ip;
	item.lpData = lpBuffer;
	return m_lpCallbackRoutine(dwReason, &item, m_lpCallbackContext);
}

BOOL CPrivateCloud::GetDeviceInformation(long ip, LPTSTR lpszDeviceId, LPTSTR lpszDeviceName, LPTSTR lpszDeviceType)
{
	CSingleLock	lock(&m_cs, TRUE);

	std::map<long, PRIVATECLOUD_ITEM>::iterator iter;
	for (iter = m_cDeviceList.begin(); iter != m_cDeviceList.end(); ++iter)
	{
		if (iter->second.ip == ip)
		{
			if (iter->second.bDeviceInformationOK)
			{
				_tcscpy_s(lpszDeviceId, DEVICE_ID_LENGTH, iter->second.szDeviceId);
				_tcscpy_s(lpszDeviceName, DEVICE_NAME_LENGTH, iter->second.szDeviceName);
				_tcscpy_s(lpszDeviceType, DEVICE_TYPE_LENGTH, iter->second.szDeviceType);
				return TRUE;
			}
			break;
		}
	}

	return FALSE;
}

BOOL CPrivateCloud::IsDeviceConnected(long ip)
{
	CSingleLock	lock(&m_cs, TRUE);

	std::map<long, PRIVATECLOUD_ITEM>::iterator iter;
	for (iter = m_cDeviceList.begin(); iter != m_cDeviceList.end(); ++iter)
	{
		if (iter->second.ip == ip)
		{
			return iter->second.bConnected;
		}
	}

	return FALSE;
}

VOID CPrivateCloud::GetConnectedDeviceList(long **pList, DWORD &dwCount)
{
	CSingleLock	lock(&m_cs, TRUE);

	*pList = NULL;
	dwCount = 0;

	std::map<long, PRIVATECLOUD_ITEM>::iterator iter;
	for (iter = m_cDeviceList.begin(); iter != m_cDeviceList.end(); ++iter)
	{
		if (iter->second.bConnected)
			dwCount++;
	}

	if (dwCount > 0)
	{
		*pList = new long[dwCount];
		
		DWORD dwIndex = 0;

		std::map<long, PRIVATECLOUD_ITEM>::iterator iter;
		for (iter = m_cDeviceList.begin(); iter != m_cDeviceList.end(); ++iter)
		{
			if (iter->second.bConnected)
			{
				(*pList)[dwIndex] = iter->second.ip;
				dwIndex++;
			}
		}
	}
}

VOID CPrivateCloud::FreeConnectedDeviceList(long *pList)
{
	delete pList;
}